package com.timothy.junk.calculate;

import android.util.Log;

import com.sina.stock.SinaStockClient;
import com.sina.stock.SinaStockInfo;
import com.sina.oefund.SinaOEFundClient;
import com.sina.oefund.SinaOEFund;
import com.sina.oefund.SinaOEFund.ParseStockInfoException;
import com.timothy.junk.common.util.DateUtil;
import com.timothy.junk.gfund.bean.GFundBean;
import com.timothy.junk.gfund.bean.GFundBeanResult;

import java.util.List;
import java.util.ArrayList;
import java.io.IOException;

/**
 * Created by IntelliJ IDEA.
 * User: qtang
 * Date: Jul 5, 2013
 * Time: 9:29:58 AM
 * To change this template use File | Settings | File Templates.
 */
public class GFundCalculator {
  public static final String LOG_TAG = "GFundCalculator";
	
  public static final double TRADING_FEE = 0.001;
  public static final double REDEMPTION_FEE = 0.005;
  public static final double SUBSCRIPTION_FEE = 0.012;

  public static final int YEAR_TRADING_DAYS = 240;
  
  //get static values
  List<GFundBean> gFundBeanList = new ArrayList<GFundBean>();
  int groupNum;

  public GFundCalculator(List<GFundBean> gFundBeanList){
  	this.gFundBeanList = gFundBeanList;
  	groupNum = gFundBeanList.size();
  }

  //input data
  String[] fundACodes;
  String[] fundBCodes;
  String[] fundMCodes;
  String[] fundMIndexCodes;
  List<Integer> fundAShareList =  new ArrayList<Integer>();
  List<Integer> fundBShareList =  new ArrayList<Integer>();
  List<Double> fundMIndexRatioList =  new ArrayList<Double>();

  public void initialAllInputData(){
      fundACodes = new String[groupNum];
      fundBCodes = new String[groupNum];
      fundMCodes = new String[groupNum];
      fundMIndexCodes = new String[groupNum];
      int i=0;
      for (GFundBean bean : gFundBeanList) {
          fundACodes[i] = bean.getFundACode();
          fundBCodes[i] = bean.getFundBCode();
          fundMCodes[i] = bean.getFundMCode();
          fundMIndexCodes[i] = bean.getFundMIndexCode();
          fundAShareList.add(bean.getFundAShare());
          fundBShareList.add(bean.getFundBShare());
          fundMIndexRatioList.add(bean.getFundMIndexRatio());
          i++;
      }
  }

  //data by SinaStockClient
  List<SinaStockInfo>  fundAList;
  List<Double> fundAPriceList;
  List<Double> fundBPriceList;
  List<SinaStockInfo> fundMIndexList;
  public void getStockData(SinaStockClient sClient){
      try {
    	  fundAList = sClient.getStockInfoList(fundACodes);
          fundAPriceList = sClient.getStockPricesList(fundACodes);
          fundBPriceList = sClient.getStockPricesList(fundBCodes);
          //get mother fund index value
          fundMIndexList = sClient.getStockInfoList(fundMIndexCodes);
      } catch (IOException e) {
          e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
      } catch (SinaStockInfo.ParseStockInfoException e) {
          e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
      } 
  }

  //data by SinaOEFundClient
  List<SinaOEFund> fundMList;
  public void getFundData(SinaOEFundClient fClient){
  	try {
			fundMList = fClient.getFundList(fundMCodes);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseStockInfoException e) {
			e.printStackTrace();
		}
  }
  
  //calculate data
  List<Double> fundMIndexRiseList = new ArrayList<Double>();
  List<Double> fundABPriceList = new ArrayList<Double>();
  List<Double> fundMValueLastDayList = new ArrayList<Double>();
  List<Double> fundMValueEstimateList = new ArrayList<Double>();
  List<Double> discountList = new ArrayList<Double>();
  
  public void calculateResult(){
      for (SinaStockInfo sInfo : fundMIndexList) {
          float mYestodayPrice = sInfo.getYestodayPrice();
          float mNowPrice = sInfo.getNowPrice();
          float rise = (mNowPrice - mYestodayPrice) / mYestodayPrice;
          fundMIndexRiseList.add(Double.valueOf(rise));
      }

      for (int i = 0 ; i< groupNum ;i++) {
          SinaOEFund fundM =  fundMList.get(i);
          SinaStockInfo fundMIndex = fundMIndexList.get(i);
          
          double value = fundM.getPrice();
          fundMValueLastDayList.add(value);

          double esValue = value;
          
          int compareResult = DateUtil.compareDate(fundMIndex.getDate(),fundM.getPriceDate());
          if( compareResult == 1){
              double ratio = Double.valueOf(fundMIndexRatioList.get(i));
              double rise = Double.valueOf(fundMIndexRiseList.get(i)) ;
              esValue =  value * (1+ rise * ratio);
          }
          
          fundMValueEstimateList.add(esValue);

          double fundAPrice = fundAPriceList.get(i);
          int fundAShare = fundAShareList.get(i);
          double fundBPrice = fundBPriceList.get(i);
          int fundBShare = fundBShareList.get(i);

          double fundABPrice = (fundAPrice * fundAShare + fundBPrice * fundBShare)/(fundAShare + fundBShare) ;
          fundABPriceList.add(fundABPrice);

          double discount = (esValue - fundABPrice)/esValue;
          discountList.add(discount);

      }
  }
  
	public static double arbSpaceDis(double discount){
		Log.i(LOG_TAG,"arbSpaceDis()...");
		
		double invest = 10000.0;
		double cost = invest * (1+TRADING_FEE);
		double gain = (invest / (1 - discount) )*(1 - REDEMPTION_FEE);
		double netgain = gain - cost;
		double mockArb = netgain/cost;
		
		Log.i(LOG_TAG,"invest="+invest);
		Log.i(LOG_TAG,"cost="+cost);
		Log.i(LOG_TAG,"gain="+gain);
		Log.i(LOG_TAG,"netgain="+netgain);
		Log.i(LOG_TAG,"mockArb="+mockArb);
		
//		double arbSpace = ((1 / (1 - discount)) * (1-REDEMPTION_FEE) - (1+TRADING_FEE) )/(1+TRADING_FEE);
		return mockArb;
	}
	
	public static double arbSpacePre(double discount) {
		double arbSpace = ((1 + discount) * (1 - TRADING_FEE) - (1 + SUBSCRIPTION_FEE))/ (1 + SUBSCRIPTION_FEE);
		return arbSpace;
	}
	
	public static double getDisYearReturn(double arb){
		return arb * YEAR_TRADING_DAYS/4;
	}
	
	public static double getPreYearReturn(double arb){
		return arb * YEAR_TRADING_DAYS/3;
	}

  public List<GFundBeanResult> getResultDataList(){
      List<GFundBeanResult> resultList = new ArrayList<GFundBeanResult>();
      for (int i = 0 ; i< groupNum ;i++) {
    	  GFundBean sBean = gFundBeanList.get(i);
    	  
          resultList.add(new GFundBeanResult(sBean.getIndex(),sBean.getFundACode(),sBean.getFundAName(),sBean.getFundAShare(),
        		  sBean.getFundBCode(),sBean.getFundBName(),sBean.getFundBShare(),
        		  sBean.getFundMCode(),sBean.getFundMName(),
        		  sBean.getFundMIndexCode(),sBean.getFundMIndexRatio(),
        		  fundAPriceList.get(i),fundBPriceList.get(i),fundABPriceList.get(i),
        		  fundMValueLastDayList.get(i),fundMIndexRiseList.get(i),fundMValueEstimateList.get(i),discountList.get(i)));
      }
      return resultList;
  }

}
